<?php defined('SYSPATH') or die('No direct script access.');
/**
 * Class for wor with AMAZON API
 * with Amazon ECS Class
 *
 * @author Odarchenko N.D. <odarchenko.n.d@gmail.com>
 */
class Model_Api
{
    public $amazonEcs;
    
    protected $cats; //временная переменная для работы ф-и getCatsAsArray()

    public static $factory = null;//фабрика, объект класса Model_Api

    public function __construct($config=null)
    {
        if(!is_object($config))
            $config = Kohana::$config->load('site');


        $this->amazonEcs = new Model_Amazon(
                    $config->AccessKeyID,
                    $config->SecretAccessKey,
                    'COM',
                    $config->AwsAssociateTag);


        $this->amazonEcs->returnType(1);
    }


    /**
     * Factory method for this class
     * @param Object $config
     * @return Model_Api
     * @author Odarchenko N.D. <odarchenko.n.d@gmail.com>
     */
    public static function factory($config=null)
    {
        if(self::$factory == null)
            self::$factory = new self($config);
        return self::$factory;
    }


    /**
     * Searching
     * @param string $cat      //category name
     * @param string $string   //query
     * @param int $page        //page number
     * @param array $additinal //Availability, Condition, Manufacturer,
     *                         // MaximumPrice, MinimumPrice, Title.
     * @author Odarchenko N.D. <odarchenko.n.d@gmail.com>
     */
    public function search($cat=172282, $string='', $page=1, $additinal=array())
    {
        $this->amazonEcs->responseGroup('Medium,Offers');
        return $this->parseMedium(
                $this->amazonEcs->category('Electronics')
                    ->search($string, $cat, $page, $additinal));
    }
    /**
     * Searching certain item by asin
     * @param string $asin      //identifier of item
     * @author Lukyanets M.V. <3ch023a@gmail.com>
     * @return array with item info
     */
    public function lookup($asin='')
    {
        $this->amazonEcs->responseGroup('ItemAttributes,Offers');
        return $this->parseLarge(
                $this->amazonEcs->lookup($asin));
    }

    public function lookupMedium($asin='')
    {
        $this->amazonEcs->responseGroup('Medium,Offers');
        return $this->parseMedium(
                $this->amazonEcs->lookup($asin));
    }
    
    public function similarItems($asin)
    {
        $this->amazonEcs->responseGroup('Medium,Offers');
        return $this->infoItems(
                $this->amazonEcs->category('Electronics')
                    ->similarityLookup($asin));
    }
    
    public function createCart($asin,$quantity) 
    {
        // по асину продукта находим его OfferListingId
        $this->amazonEcs->responseGroup('Offers');
            $id = $this->amazonEcs->lookup($asin);
        if(isset($id['Items']['Item']['Offers']['Offer']['OfferListing']['OfferListingId']))
        {
            $offerListingId = $id['Items']['Item']['Offers']['Offer']['OfferListing']['OfferListingId'];
        }
        //else return FALSE; по идее если не нашли то и добавить не можем
        // эту ветку надо прописать, надо вернуть сообщение об ошибке
        else
        {
            throw new Exception('Cant add to cart');            
        }
        $this->amazonEcs->responseGroup('Cart');
        return $this->parseCart($this->amazonEcs->createCart($offerListingId,$quantity ));
   
    }
    /**
     * 
     * @param string $asin //ID
     * @param string  $cartId // identifies a cart
     * @param string  $hmac // The Hash Message Authentication Code
     * @return array
     */
    public function addCart($asin, $cartId, $hmac, $quantity)
    {
        // по асину продукта находим его OfferListingId
        $this->amazonEcs->responseGroup('Offers');
        $id = $this->amazonEcs->lookup($asin);
        if(isset($id['Items']['Item']['Offers']['Offer']['OfferListing']['OfferListingId']))
        {
            $offerListingId = $id['Items']['Item']['Offers']['Offer']
            ['OfferListing']['OfferListingId'];
        }
        //else return FALSE; по идее если не нашли то и добавить не можем
        // эту ветку надо прописать, надо вернуть сообщение об ошибке
        else
        {
            throw new Exception('Cant add to cart');
            
        }
        $this->amazonEcs->responseGroup('Cart');
        
        return $this->parseCart($this->amazonEcs->cartAdd($offerListingId, $cartId, $hmac, $quantity));
        
    }
    
    public function delItem($asin, $cartId, $hmac, $cartItemID)
    {
        $this->amazonEcs->responseGroup('Offers');
            $id = $this->amazonEcs->lookup($asin);
        if(isset($id['Items']['Item']['Offers']['Offer']['OfferListing']['OfferListingId']))
        {
            $offerListingId = $id['Items']['Item']['Offers']['Offer']['OfferListing']['OfferListingId'];
        }
        $this->amazonEcs->responseGroup('Cart');
       // echo $asin.'<br>';
       // echo $offerListingId;
        //exit;
        return $this->parseCart($this->amazonEcs->cartDelItem($offerListingId, $cartId, $hmac, $cartItemID));        
    }
    
    public function clearCart($cartId, $hmac)
    {
        
        return $this->$this->amazonEcs->cartClear($cartId, $hmac);
    }
    
    public function getCart($cartId, $hmac) 
    {   
        $this->amazonEcs->responseGroup('Cart');
        return $this->parseGetCart($this->amazonEcs->cartGet($cartId, $hmac));
    }
    
    public function getCartFull($cartId, $hmac) 
    {   
        $this->amazonEcs->responseGroup('Cart');
        return $this->parseGetCartFull($this->amazonEcs->cartGet($cartId, $hmac));
    }
    
    public function multipleCreateCart($items)
    {
        $this->amazonEcs->responseGroup('Cart');
        return $this->parseCart($this->amazonEcs->multipleCreateCart($items));
    }


    /**
     * Упрощение массива из ответа API для поиска
     * @param array $response
     * @return array
     */
    private function parseMedium($response)
    {
        //$user = Auth::instance()->get_user(null);
        //$user_id = isset($user)? $user->id : 0;
        $items = array();
        $totalPages = isset($response['Items']['TotalPages']) ?
                min(10, $response['Items']['TotalPages']) : 0;
        // найден 1 товар
        if(isset($response['Items']['Item']['ASIN'],
            $response['Items']['Item']['ItemAttributes']))
        {
            $i = $response['Items']['Item'];
            $items [] = array(
                    'ASIN' => $i['ASIN'],//ID
                    'src' => isset($i['MediumImage']['URL']) ?
                        $i['MediumImage']['URL'] : '/images/no_image160.png',
                    'price' =>
                        isset($i['Offers']['Offer']['OfferListing']['Price']['FormattedPrice'])?
                        $i['Offers']['Offer']['OfferListing']['Price']['FormattedPrice'] : ' Not Available ',
                    'model' => isset($i['ItemAttributes']['Model'])?
                        $i['ItemAttributes']['Model'] : ' - ',
                    'title' => isset($i['ItemAttributes']['Title'])?
                        $i['ItemAttributes']['Title'] : ' Product ' . $i['ASIN'],
                    'wList' => 0,
                );
        } // найдено несколько товаров
        elseif(isset($response['Items']['Item']))
            foreach($response['Items']['Item'] as $i)
                if(isset($i['ASIN']))
                {
                    $items[] = array(
                        'ASIN' => $i['ASIN'],//ID
                        'src' => isset($i['MediumImage']['URL']) ?
                            $i['MediumImage']['URL'] : '/images/no_image160.png',
                        'price' =>
                            isset($i['Offers']['Offer']['OfferListing']['Price']['FormattedPrice'])?
                            $i['Offers']['Offer']['OfferListing']['Price']['FormattedPrice'] : ' Not Available ',
                        'model' => isset($i['ItemAttributes']['Model'])?
                            $i['ItemAttributes']['Model'] : ' - ',
                        'title' => isset($i['ItemAttributes']['Title'])?
                            $i['ItemAttributes']['Title'] : ' Product ' . $i['ASIN'],
                        'wlBut' => 0, // определяем показывать ли кнопку добавления в вишлист этого товара этому юзеру
                    );
                }

        if(count($items))
            $items [] = $totalPages;//последний элемент массива - количество страниц всего
        return $items;
    }

    /**
     * Упрощение массива из ответа API для отображения инфы о товаре
     * @param array $response
     * @return array
     */

    private function parseLarge($response)
    {
        //print_r($response);
        $item = array();
        if(isset($response['Items']['Item']['ASIN'],
            $response['Items']['Item']['ItemAttributes']))
        {
            $this->amazonEcs->responseGroup('Images');
            $img = $this->amazonEcs->lookup($response['Items']['Item']['ASIN']);
            $item['asin'] = $response['Items']['Item']['ASIN'];
            $attr = $response['Items']['Item']['ItemAttributes'];//для сокращения
            $item['src'] = isset($img['Items']['Item']['LargeImage']['URL']) ?
                            $img['Items']['Item']['LargeImage']['URL'] :
                        '/images/no_image160.png';
            $item['src_height'] = isset(
                $img['Items']['Item']['LargeImage']['Height']) ?
                    $img['Items']['Item']['LargeImage']['Height'] : '160';

            //
            $item['Available'] = isset($response['Items']['Item']['Offers']['Offer']['OfferListing']['OfferListingId'])?
                TRUE: FALSE;
            $item['Price'] = isset($response['Items']['Item']['Offers']['Offer']['OfferListing']['Price']['FormattedPrice'])?
                $response['Items']['Item']['Offers']['Offer']['OfferListing']['Price']['FormattedPrice'] : ' Not Available ';

            $item['Title'] = ' Product ' . $item['asin'];//по умолчанию

            //Заполняем массив теми dэлементами из списка, которые найдены в ответе
            foreach(array('Price','Title','Binding','Brand','Author','Creator',
                'ReleaseDate','Edition','Format', 'Color','Category') as $key)
                if(isset($attr[$key]))
                {
                    $key2 = $key;
                    if($key == 'Binding')
                        $key = 'Category';
                    elseif($key == 'ReleaseDate')
                        $key = 'Release date';
                    elseif($key == 'Price')
                    {
                        $item[$key] = $attr['ListPrice']['FormattedPrice'];
                        continue;
                    }
                    $item[$key] = $attr[$key2];
                }

            if(isset($response['Items']['Variations']['Item']['ItemAttributes']['HardwarePlatform']))
                $item['Hardware platform'] = $attr['HardwarePlatform'];

            if(isset($attr['Languages']['Language']['AudioFormat']))
                $item['Audio format'] = $attr['Languages']['Language']['AudioFormat'];

            // если есть фичи - перепишим их в массив фич
            if(isset($attr['Feature']))
            {
                if(is_array($attr['Feature']))
                {
                    $item['Feature'] = array();
                    foreach ($attr['Feature'] as $feature)
                        $item['Feature'][] = $feature;
                }
                else
                    $item['Feature'] = array($attr['Feature']);
            }

            //Размеры
            foreach(array('Weight','Height','Lenght','Width') as $key)
                if(isset($attr['ItemDimensions'][$key]))
                    $item[$key] = $attr['ItemDimensions'][$key]['_']
                            .' ('. $attr['ItemDimensions'][$key]['Units'].')';
            //похожий перебор уже есть, но мы так сохраним порядок заполнения
            foreach(array('Size','Label','Manufacturer','Model','Platform',
                'OperatingSystem', 'NumberOfDiscs','Publisher','Studio',
                'PartNumber', 'ProductGroup','ProductTypeName') as $key)
                if(isset($attr[$key]))
                {
                    $key2 = $key;
                    if($key == 'OperatingSystem')
                        $key = 'Operating system';
                    elseif($key == 'NumberOfDiscs')
                        $key = 'Number of discs';
                    elseif($key == 'PartNumber')
                        $key = 'Part number';
                    elseif($key == 'ProductGroup')
                        $key = 'Product group';
                    elseif($key == 'ProductTypeName')
                        $key = 'Product type name';

                    $item[$key] = $attr[$key2];
                }
        }
        return $item;
    }
    /**
     * Упрощение массива из ответа API для поиска похожих
     * @param array $response
     * @return array
     */
    private function infoItems($response)
    {
        if(isset($response['Items']['Item']['ASIN']))
        {
            $i = $response['Items']['Item'];
            return array(array(
                'ASIN' => $i['ASIN'],//ID
                'src' => isset($i['MediumImage']['URL'])?
                    $i['MediumImage']['URL'] : '/images/no_image160.png',

                'title' => isset($i['ItemAttributes']['Title'])?
                    $i['ItemAttributes']['Title']
                    :
                    ' Product ' . $i['ASIN'],
                'price' => isset(
                    $i['Offers']['Offer']['OfferListing']['Price']['FormattedPrice'])?
                        $i['Offers']['Offer']['OfferListing']['Price']['FormattedPrice']['FormattedPrice'] : ' Not Available ',
            ));
        }

        $items = array();
        if(isset($response['Items']['Item']))
        {
            foreach($response['Items']['Item'] as $k => $i)
                if(isset($i['ASIN']))
                {
                    $items[] = array(
                        'ASIN' => $i['ASIN'],//ID
                        'src' => isset($i['MediumImage']['URL'])?
                            $i['MediumImage']['URL'] : '/images/no_image160.png',

                        'title' => isset($i['ItemAttributes']['Title'])?
                            $i['ItemAttributes']['Title']
                            :
                            ' Product ' . $i['ASIN'],
                        'price' => isset(
                            $i['Offers']['Offer']['OfferListing']['Price']['FormattedPrice'])?
                                $i['Offers']['Offer']['OfferListing']['Price']['FormattedPrice'] : ' Not Available ',
                    );
                 }
         }
         return $items;
     }

     /**
      * Упрощение массива из ответа API для добавления в корзину
      * Когда в корзине 1 товар
      * @param array $response
      * @return array
      */
     private function parseCart($response)
     {
        //print_r($response);
        $cart = array();
        if (isset($response['Cart']['CartId']))
        {
            $cart['CartId'] = $response['Cart']['CartId'];
            $cart['HMAC'] = $response['Cart']['HMAC'];
            //echo "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD".  count($response['Cart']['CartItems']['CartItem']);
            //print_r($response['Cart']['CartItems']['CartItem']);

            if (isset($response['Cart']['CartItems']['CartItem']['CartItemId']))
            {
                $cart['CartItemId'] = $response['Cart']['CartItems']['CartItem']['CartItemId'];
                $cart['ASIN'] = $response['Cart']['CartItems']['CartItem']['ASIN'];
                $cart['Quantity'] = $response['Cart']['CartItems']['CartItem']['Quantity'];
                //print_r($cart);
            }
            else
            if (isset($response['Cart']['CartItems']['CartItem']))
            {
                for ($i = 0; $i < count($response['Cart']['CartItems']['CartItem']); $i++)
               {
                   $cart['Item'][$i]['CartItemId'] = $response['Cart']['CartItems']['CartItem'][$i]['CartItemId'];
                   $cart['Item'][$i]['ASIN'] = $response['Cart']['CartItems']['CartItem'][$i]['ASIN'];
                   $cart['Item'][$i]['Quantity'] = $response['Cart']['CartItems']['CartItem'][$i]['Quantity'];
                   //print_r($cart);

               }
                //$cart['CartItemId'] = $response['Cart']['CartItems']['CartItem']['CartItemId'];
                //$cart['ASIN'] = $response['Cart']['CartItems']['CartItem']['ASIN'];
            }
        }
        $cart['purchaseURL'] = isset($response['Cart']['PurchaseURL']) ?
                $response['Cart']['PurchaseURL'] : '';
        //print_r($cart);
        return $cart;
     }
     /**
      * Упрощение массива из ответа API для вывода элементов добавленных в корзину
      * Когда в корзине больше 1 товара
      * @param array $response
      * @return array
      */
     private function parseGetCart($response) // только что созданная корзина, 1 айтем
     {

         $items = array();
         if(isset($response['Cart']['CartItems']['CartItem']))
         {
             $j=0;
             //foreach($response['Cart']['CartItems']['CartItem'] as $key => $i)
             //{
                 if(isset($response['Cart']['CartItems']['CartItem']['ASIN'])
                        // && $key !== 'SubTotal'
                         )
                 {
                     $this->amazonEcs->responseGroup('Images');
                     $img = $this->amazonEcs->lookup($response['Cart']['CartItems']['CartItem']['ASIN']);

                     $items[$j] = array(
                     'ASIN'=>$response['Cart']['CartItems']['CartItem']['ASIN'],
                     'Title' => isset($response['Cart']['CartItems']['CartItem']['Title']) ?
                         $response['Cart']['CartItems']['CartItem']['Title'] : 'No Title',
                     'Price' => isset($response['Cart']['CartItems']['CartItem']['Price']['FormattedPrice']) ?
                         $response['Cart']['CartItems']['CartItem']['Price']['FormattedPrice'] : 'Not Available',
                     'Quantity' => isset($response['Cart']['CartItems']['CartItem']['Quantity']) ?
                         $response['Cart']['CartItems']['CartItem']['Quantity'] : 'No Quantity',
                     'src' => isset($img['Items']['Item']['MediumImage']['URL']) ?
                                   $img['Items']['Item']['MediumImage']['URL'] :
                               '/images/no_image160.png',
                     'src_height' => isset($img['Items']['Item']['MediumImage']['Height']) ?
                           $img['Items']['Item']['MediumImage']['Height'] : '160',
                     'SellerNickname' => isset($response['Cart']['CartItems']['CartItem']['SellerNickname'])?
                         $response['Cart']['CartItems']['CartItem']['SellerNickname'] : 'Not defined',
                     'ProductGroup'=> isset($response['Cart']['CartItems']['CartItem']['ProductGroup'])?
                         $response['Cart']['CartItems']['CartItem']['ProductGroup'] : 'Not defined',

                     );

                 $j++;
                 }
             //}


         }
         $items['purchaseURL'] = isset($response['Cart']['PurchaseURL']) ?
                    $response['Cart']['PurchaseURL'] : '';
         $items['Total'] = isset($response['Cart']['SubTotal']['FormattedPrice']) ?
                    $response['Cart']['SubTotal']['FormattedPrice'] : '$0.00';
         return $items;
     }

     private function parseGetCartFull($response)
     {
         //echo'<br><br>';
         //print_r($response);
         $items = array();
         if(isset($response['Cart']['CartItems']['CartItem']))
         {
             //$items[0] = $response['Cart']['CartItems']['SubTotal']['FormattedPrice'];
             // находи изображение

             $j=0;
             foreach($response['Cart']['CartItems']['CartItem'] as $key => $i)
             {
                 //echo $key;
                 // если в корзине 1 айтем
                 if($key==='CartItemId')
                     return $this->parseGetCart($response);
                 else
                 {
                    if(isset($i['ASIN']))
                    {
                        $this->amazonEcs->responseGroup('Images');
                        $img = $this->amazonEcs->lookup($i['ASIN']);

                        $items[$j] = array(
                            'ASIN'           => $i['ASIN'],
                            'Title'          => isset($i['Title']) ?
                                $i['Title'] : 'No Title',
                            'Price'          => isset($i['Price']['FormattedPrice']) ?
                                $i['Price']['FormattedPrice'] : 'Not Available',
                            'Quantity'       => isset($i['Quantity']) ?
                                $i['Quantity'] : 'No Quantity',
                            'src'            => isset($img['Items']['Item']['MediumImage']['URL'])
                                ?
                                $img['Items']['Item']['MediumImage']['URL']
                                :
                                '/images/no_image160.png',
                            'src_height'     => isset($img['Items']['Item']['MediumImage']['Height']) ?
                                $img['Items']['Item']['MediumImage']['Height'] : '160',
                            'SellerNickname' => isset($i['SellerNickname']) ?
                                $i['SellerNickname'] : 'Not defined',
                            'ProductGroup'   => isset($i['ProductGroup']) ?
                                $i['ProductGroup'] : 'Not defined',

                        );

                    $j++;
                    }
                 }
             }
         }

         $items['Total'] = isset($response['Cart']['SubTotal']['FormattedPrice']) ?
                    $response['Cart']['SubTotal']['FormattedPrice'] : '$0.00';

         $items['purchaseURL'] = isset($response['Cart']['PurchaseURL']) ?
                    $response['Cart']['PurchaseURL'] : '$0.00';
         return $items;
     }

     public function nodeChilds($id = 172282)//Electronics = 172282
     {
         $this->amazonEcs->responseGroup('BrowseNodeInfo');
         return $response = $this->amazonEcs->browseNodeLookup($id);
         //print_r($response);
     }
     /**
      * NOTE: желательно заменить статическое обновление на инф. из кэша категорий
      * @return array категории и их node
      */
     public static function catsForSearch()
     {
         return array(
             281407 => 'Accessories & Supplies',
             502394 => 'Camera & Photo',
             2811119011 => 'Cell Phones & Accessories',
             541966 => 'Computers & Accessories',
             2642125011 => 'eBook Readers & Accessories',
             2242348011 => 'Electronics Warranties',
             172526 => 'GPS & Navigation',
             667846011 => 'Home Audio',
             172574 => 'Office Electronics',
             172623 => 'Portable Audio & Video',
             524136 => 'Security & Surveillance',
             16285901 => 'Service & Replacement Plans',
             1266092011 => 'Television & Video',
             3248684011 => 'Car & Vehicle Electronics'
         );
     }

    //protected $i1 = 0;//отладочная переменная!

    /**
     * Возвращает массив дерева категорий
     * @return array
     */
    public function getCatsAsArray()
    {
        // TODO: cashing into file

        $arr = unserialize(base64_decode(file_get_contents(APPPATH . 'cache/cats')));
        return $arr;

//        // get in recurve function array
//        $this->cats = array();
//        $this->amazonEcs->responseGroup('BrowseNodeInfo');
//        $this->fillCatsRecursive(493964, $this->cats);
//        return $this->cats;
    }

    /**
     * Рекурсивная ф-я для получения категорий с api
     * @param int $id
     * @param &array $a
     * @return void
     */
    protected function fillCatsRecursive($id, &$a)
    {
        //if($this->i1++ > 19)//отладочный код!
        //    return;

        $resp = $this->amazonEcs->browseNodeLookup($id);

        if(!isset($resp['BrowseNodes']['BrowseNode']['Children']['BrowseNode'][0]))
            return;

        foreach($resp['BrowseNodes']['BrowseNode']['Children']['BrowseNode'] as $c)
        {
            $t = array();
            $this->fillCatsRecursive($c['BrowseNodeId'], $t);
            $a[] = array("Name" => $c['Name'], 'id' => $c['BrowseNodeId'], 'children' => $t);
        }
    }

    public function getItemInfo($asin)
    {
        $this->amazonEcs->responseGroup('Medium,Offers');
        $response = $this->amazonEcs->lookup($asin);
        if(isset($response['Items']['Item']['ASIN']))
        {
            $item = array(
                'asin' => $response['Items']['Item']['ASIN'],//ID
                'src' => isset($response['Items']['Item']['MediumImage']['URL']) ?
                    $response['Items']['Item']['MediumImage']['URL'] : '/images/no_image160.png',
                'price' =>
                    isset($response['Items']['Item']['Offers']['Offer']['OfferListing']['Price']['FormattedPrice'])?
                    $response['Items']['Item']['Offers']['Offer']['OfferListing']['Price']['FormattedPrice'] : ' Not Available ',
                'title' => isset($response['Items']['Item']['ItemAttributes']['Title'])?
                    $response['Items']['Item']['ItemAttributes']['Title'] : ' Product ' . $response['Items']['Item']['ASIN'],
            );
        }
        return $item;
    }
}
